/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

//package ProjetoGeral.ParaAmbos;

//import ProjetoGeral.Cliente.Arquivo;
//import ProjetoGeral.Servidor.ListaArquivos;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Larissa
 */
public class TCPEchoServerClient implements Runnable{
        private static final int BUFSIZE = 32; // Tamanho do buffer de recepcao
        
        private Socket connection;
        private int ID;
        private String mensagem;
        private char comando;
        private String nodeOrigem;
        private String nomeArquivoRecebido;//nome do arquivo recebido
        private String nodeDestino;
        private int tamanho_buffer = 4096;

        private TCPEchoServerClient(Socket s, int i) {
            this.connection = s;
            this.ID = i;
        }
        
        public void criarArquivo() throws IOException{
            File arquivo = new File('C'+this.nomeArquivoRecebido);

            if(arquivo.exists() == false){
                boolean createNewFile = arquivo.createNewFile();
            }
        }
        
        public void enviarArquivo() throws IOException{//Envia o arquivo para o outro node, só para leitura!
                ObjectOutputStream saida = new ObjectOutputStream(connection.getOutputStream());
                FileInputStream file = new FileInputStream(this.nomeArquivoRecebido);
                byte[] buffer = new byte[this.tamanho_buffer]; //tamanho do arquivo = 4K

                while(true){
                    int tamanho_file = file.read(buffer);
                    if(tamanho_file == -1)break;
                    saida.write(buffer, 0, tamanho_file);
                }
                file.close();
        }
        
        public void removerArquivo(){//Remove o arquivo da pasta
            File file = new File(this.nomeArquivoRecebido);
            boolean success = file.delete();
            if (success) {
                System.out.println("O arquivo foi deletado com sucesso!"); 
            }
            else{
                System.out.println("Não foi possível deletar o arquivo!"); 
            }
        }
        
        public void tomarDecisao(char c) throws IOException{
            if(c == 'C'){//criar arquivo local e mandar um feedback para o nodeMestre incluir o arquivo na lista
                this.criarArquivo();
            }
            if(c == 'L'){//só enviar ele para o node que fez a requisicao
                this.enviarArquivo();
            }
            if(c == 'E'){//apagar o arquivo e mandar um feedback para o nodeMestre excluir o arquivo da lista
                this.removerArquivo();
            }
            if(c == 'M'){//mover o arquivo desse local para o node requisitante
                this.enviarArquivo();
                this.removerArquivo();                
            }
        }

        public static void main(String[] args) throws IOException {
            int servPort = 4000;
            int count = 0;//Count serve para contar quantos sockets estao abertos. 
            try{
                ServerSocket socket1 = new ServerSocket(servPort);//Cria o socket na porta servPort
                System.out.println("Servidor pronto para aceitar múltiplas conexoes...");
                while (true) {
                      Socket connection = socket1.accept();//aceita a conexao
                      Runnable runnable = new TCPEchoServerClient(connection, ++count);//Aqui o socket vai incrementando conforme um socket é aberto
                      Thread thread = new Thread(runnable);
                      thread.start();
                }
            }
            catch (IOException e) {}
        }
        /*The run() method’s responsibility is to run the block of code that we want threaded.*/
        
        public void run() {
                       
            try {
                BufferedInputStream is = new BufferedInputStream(connection.getInputStream());
                InputStreamReader in = new InputStreamReader(is);//Para recepcao de dados
                OutputStream out = connection.getOutputStream();
                int character;
                StringBuffer mensagemRecebida = new StringBuffer();
                //Pega o nome do arquivo
                while((character = in.read()) != (int)'#') {//A '#' indica o final do nome do arquivo
                  mensagemRecebida.append((char)character);
                }
                
                this.mensagem = mensagemRecebida.toString();
                
                System.out.println(this.mensagem);
                int indice_final = this.retornarArquivoENode();
                this.comando = this.mensagem.charAt(0);//pega o comando
                this.nodeOrigem = this.mensagem.substring(1, indice_final);//pega o nó de origem
                this.nomeArquivoRecebido = this.mensagem.substring(indice_final+1);//pega o nome do arquivo
                System.out.println(this.nomeArquivoRecebido);
                this.tomarDecisao(this.comando);//fazer o que deve ser feito
                
            } catch (IOException ex){
                Logger.getLogger(TCPEchoServerClient.class.getName()).log(Level.SEVERE, null, ex);
            }
            try {
                this.connection.close();
            } catch (IOException ex) {
                Logger.getLogger(TCPEchoServerClient.class.getName()).log(Level.SEVERE, null, ex);
            }
                
    }
    public int retornarArquivoENode(){
            int i = 0;
            while(this.mensagem.charAt(i) != '*'){
                i++;
            }
            return (i);
    }
}
